﻿
// **************************************************************************
//    Class Created by Mick Doherty (Dotnetrix) May 2010
//    http://dotnetrix.co.uk/
//
//    ...for GlassUI (an AeroGlass UI Library)
//    http://glassui.codeplex.com/
// **************************************************************************

using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Windows.Forms;
using GlassUI.Design;

namespace GlassUI
{
    [Designer(typeof(NonClientControlDesigner))]
    [Docking(DockingBehavior.Ask)]
    public class HeaderPanel : ScrollableControl
    {

        public HeaderPanel()
            : base()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, true);
        }

        #region Events

        public event PaintEventHandler PaintNonClient;

        public event EventHandler NonClientClick;
        public event EventHandler NonClientDoubleClick;

        public event EventHandler NonClientMouseEnter;
        public event EventHandler NonClientMouseHover;
        public event EventHandler NonClientMouseLeave;

        public event MouseEventHandler NonClientMouseDown;
        public event MouseEventHandler NonClientMouseMove;
        public event MouseEventHandler NonClientMouseUp;

        #endregion

        #region Private Instance Variables

        private bool defaultToGlass = true;

        private bool mousePressed;
        internal bool mouseIn;

        private NativeMethods.USER32.TRACKMOUSEEVENT trackMouse;

        private Color headerBackColor = SystemColors.ActiveCaption;
        private Color headerForeColor = SystemColors.ActiveCaptionText;
        private Font headerFont = SystemFonts.CaptionFont;

        private ImageList imageList;
        private Image image;
        private int imageIndex = -1;
        private string imageKey = "";

        #endregion

        #region Properties

        [Category("Behavior")]
        [DefaultValue(true)]
        [GlassUIDescription("DefaultToGlassDescription")]
        public bool DefaultToGlass
        {
            get { return defaultToGlass; }
            set { defaultToGlass = value; }
        }

        public override System.Drawing.Color BackColor
        {
            get
            {
                GlassForm form = this.FindForm() as GlassForm;
                if (form != null)
                {
                    if (DefaultToGlass && form.ControlIsOnGlass(this))
                        return Color.Transparent;
                }
                return base.BackColor;
            }
            set
            {
                base.BackColor = value;
            }
        }

        [Category("Appearance")]
        [GlassUIDescription("ButtonImageListDescr", "System.Windows.Forms")]
        public virtual ImageList ImageList
        {
            get { return imageList; }
            set
            {
                imageList = value;
                this.InvokeNCPaint();
            }
        }
        protected bool ShouldSerializeImageList()
        {
            return imageList != null;
        }
        private void ResetImageList()
        {
            ImageList = null;
        }

        [GlassUIDescription("ButtonImageDescr", "System.Windows.Forms")]
        [DefaultValue(typeof(Image),"")]
        public Image Image
        {
            get { return image; }
            set
            {
                if (value != image)
                {
                    image = value;
                    if (this.AutoSize)
                        this.OnSizeChanged(EventArgs.Empty);
                    this.InvokeNCPaint();
                }
            }
        }

        [Category("Appearance"), DefaultValue(-1)]
        [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design", typeof(UITypeEditor))]
        [GlassUIDescription("ButtonImageIndexDescr", "System.Windows.Forms")]
        [TypeConverter(typeof(ImageIndexConverter))]
        public int ImageIndex
        {
            get
            {
                if (ImageList == null)
                    return -1;
                if (ImageList.Images.Count < imageIndex)
                    return -1;
                return imageIndex;
            }
            set
            {
                imageIndex = value;
                if (imageKey.Length > 0)
                    imageKey = "";
                if (this.AutoSize)
                    this.OnSizeChanged(EventArgs.Empty);
                this.InvokeNCPaint();
            }
        }

        [DefaultValue("")]
        [Editor("System.Windows.Forms.Design.ImageIndexEditor, System.Design", typeof(UITypeEditor))]
        [GlassUIDescription("ButtonImageIndexDescr", "System.Windows.Forms")]
        [RefreshProperties(RefreshProperties.All)]
        [TypeConverter(typeof(ImageKeyConverter))]
        public string ImageKey
        {
            get
            {
                if (ImageList == null)
                    return "";
                if (!ImageList.Images.ContainsKey(imageKey))
                    return "";
                return imageKey;
            }
            set
            {
                imageKey = value;
                if (imageIndex != -1)
                    imageIndex = -1;
                if (this.AutoSize)
                    this.OnSizeChanged(EventArgs.Empty);
                this.InvokeNCPaint();
            }
        }

        [DefaultValue(typeof(Color), "ActiveCaption")]
        [GlassUIDescription("HeaderBackColorDescription")]
        public Color HeaderBackColor
        {
            get 
            {
                //GlassForm form = this.FindForm() as GlassForm;
                //if (form != null)
                //{
                //    if (this.DefaultToGlass && form.ControlIsOnGlass(this))
                //        return Color.Transparent;
                //}
                return headerBackColor; 
            }
            set
            {
                if (headerBackColor != value)
                {
                    headerBackColor = value;
                    this.InvokeNCPaint();
                }
            }
        }

        [DefaultValue(typeof(Color), "ActiveCaptionText")]
        [GlassUIDescription("HeaderForeColorDescription")]
        public Color HeaderForeColor
        {
            get { return headerForeColor; }
            set
            {
                if (headerForeColor != value)
                {
                    headerForeColor = value;
                    this.InvokeNCPaint();
                }
            }
        }

        [GlassUIDescription("HeaderFontDescription")]
        public Font HeaderFont
        {
            get { return headerFont; }
            set
            {
                if (headerFont != value)
                {
                    headerFont = value;
                    this.UpdateNonClient();
                }
            }
        }
        private bool ShouldSerializeHeaderFont()
        {
            return !this.HeaderFont.Equals(SystemFonts.CaptionFont);
        }
        private void ResetHeaderFont()
        {
            this.HeaderFont = SystemFonts.CaptionFont;
        }
        
#endregion

        protected override void OnCreateControl()
        {
            base.OnCreateControl();
            InitTrackmouse();
        }

        [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        private void InitTrackmouse()
        {
            this.trackMouse = new NativeMethods.USER32.TRACKMOUSEEVENT();
            this.trackMouse.cbSize = Marshal.SizeOf(this.trackMouse);
            this.trackMouse.dwHoverTime = NativeMethods.USER32.HOVER_DEFAULT;
            this.trackMouse.hwndTrack = this.Handle;
        }

        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        protected override void WndProc(ref Message m)
        {
            if (PreWndProc(ref m))
            {
                base.WndProc(ref m);
                PostWndProc(ref m);
            }
        }

        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        private bool PreWndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case (int)NativeMethods.USER32.WindowMessage.WM_ERASEBKGND:
                    return false;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCCALCSIZE:
                    if (m.WParam.Equals(IntPtr.Zero))
                    {
                        NativeMethods.USER32.RECT rc = (NativeMethods.USER32.RECT)(m.GetLParam(typeof(NativeMethods.USER32.RECT)));
                        Rectangle r = rc.ToRectangle();
                        this.OnNonClientCalcSize(ref r);
                        Marshal.StructureToPtr(new NativeMethods.USER32.RECT(r), m.LParam, true);
                    }
                    else
                    {
                        NativeMethods.USER32.NCCALCSIZE_PARAMS csp = (NativeMethods.USER32.NCCALCSIZE_PARAMS)(m.GetLParam(typeof(NativeMethods.USER32.NCCALCSIZE_PARAMS)));
                        Rectangle r = csp.rgrc0.ToRectangle();
                        this.OnNonClientCalcSize(ref r);
                        csp.rgrc0 = new NativeMethods.USER32.RECT(r);
                        Marshal.StructureToPtr(csp, m.LParam, true);
                    }
                    m.Result = IntPtr.Zero;
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCPAINT:
                    this.NCPaint();
                    m.WParam = GetHRegion();
                    base.DefWndProc(ref m);
                    NativeMethods.GDI32.DeleteObject(m.WParam);
                    m.Result = IntPtr.Zero;
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_PRINT:
                    NativeMethods.USER32.PRINTFLAGS prf = (NativeMethods.USER32.PRINTFLAGS)m.LParam.ToInt32();
                    if ((prf & NativeMethods.USER32.PRINTFLAGS.NONCLIENT) == NativeMethods.USER32.PRINTFLAGS.NONCLIENT)
                    {
                        if ((prf & NativeMethods.USER32.PRINTFLAGS.CHECKVISIBLE) != NativeMethods.USER32.PRINTFLAGS.CHECKVISIBLE || this.Visible)
                        {
                            if ((prf & NativeMethods.USER32.PRINTFLAGS.CLIENT) == NativeMethods.USER32.PRINTFLAGS.CLIENT)
                            {
                                using (Graphics g = Graphics.FromHdc(m.WParam))
                                {
                                    GraphicsContainer gctr = g.BeginContainer();
                                    Rectangle TranslateRect = new Rectangle(this.Location, this.Size);
                                    PaintEventArgs pe = new PaintEventArgs(g, TranslateRect);
                                    g.TranslateTransform(-this.Left, -this.Top);
                                    this.InvokePaintBackground(this, pe);
                                    this.InvokePaint(this, pe);
                                    g.ResetTransform();
                                    g.EndContainer(gctr);
                                }
                            }
                            this.NCPaint(m.WParam);
                        }
                    }
                    break;
            }
            return true;
        }

        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        private void PostWndProc(ref Message m)
        {
            Point pt = Point.Empty;
            switch (m.Msg)
            {
                case (int)NativeMethods.USER32.WindowMessage.WM_NCHITTEST:
                    if ((NativeMethods.USER32.NCHITTESTRESULT)m.Result.ToInt32() == NativeMethods.USER32.NCHITTESTRESULT.NOWHERE)
                        m.Result = new IntPtr((int)NativeMethods.USER32.NCHITTESTRESULT.BORDER);
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCLBUTTONDBLCLK:
                case (int)NativeMethods.USER32.WindowMessage.WM_NCMBUTTONDBLCLK:
                case (int)NativeMethods.USER32.WindowMessage.WM_NCRBUTTONDBLCLK:
                case (int)NativeMethods.USER32.WindowMessage.WM_NCXBUTTONDBLCLK:
                    this.OnNonClientDoubleClick(EventArgs.Empty);
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCLBUTTONDOWN:
                    this.mousePressed = true;
                    pt = this.PointToControl(new Point(m.LParam.ToInt32()));
                    this.OnNonClientMouseDown(new MouseEventArgs(MouseButtons.Left, 0, pt.X, pt.Y, 0));
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCLBUTTONUP:
                    if (this.mousePressed)
                    {
                        this.mousePressed = false;
                        this.OnNonClientClick(EventArgs.Empty);
                    }
                    pt = this.PointToControl(new Point(m.LParam.ToInt32()));
                    this.OnNonClientMouseUp(new MouseEventArgs(MouseButtons.Left, 0, pt.X, pt.Y, 0));
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCMBUTTONDOWN:
                    this.mousePressed = true;
                    pt = this.PointToControl(new Point(m.LParam.ToInt32()));
                    this.OnNonClientMouseDown(new MouseEventArgs(MouseButtons.Middle, 0, pt.X, pt.Y, 0));
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCMBUTTONUP:
                    if (this.mousePressed)
                    {
                        this.mousePressed = false;
                        this.OnNonClientClick(EventArgs.Empty);
                    }
                    pt = this.PointToControl(new Point(m.LParam.ToInt32()));
                    this.OnNonClientMouseUp(new MouseEventArgs(MouseButtons.Middle, 0, pt.X, pt.Y, 0));
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCMOUSEHOVER:
                    this.OnNonClientMouseHover(EventArgs.Empty);
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCMOUSELEAVE:
                    this.mouseIn = false;
                    this.OnNonClientMouseLeave(EventArgs.Empty);
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCMOUSEMOVE:
                    if (!this.mouseIn)
                    {
                        this.mouseIn = true;
                        this.OnNonClientMouseEnter(EventArgs.Empty);
                        this.trackMouse.dwFlags = NativeMethods.USER32.TRACKMOUSEEVENTFLAGS.NONCLIENT | NativeMethods.USER32.TRACKMOUSEEVENTFLAGS.LEAVE | NativeMethods.USER32.TRACKMOUSEEVENTFLAGS.HOVER;
                        this.trackMouse.hwndTrack = this.Handle;
                        NativeMethods.COMCTL32._TrackMouseEvent(ref this.trackMouse);
                    }
                    pt = this.PointToControl(new Point(m.LParam.ToInt32()));
                    this.OnNonClientMouseMove(new MouseEventArgs(MouseButtons.None, 0, pt.X, pt.Y, 0));
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCRBUTTONDOWN:
                    this.mousePressed = true;
                    pt = this.PointToControl(new Point(m.LParam.ToInt32()));
                    this.OnNonClientMouseDown(new MouseEventArgs(MouseButtons.Right, 0, pt.X, pt.Y, 0));
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCRBUTTONUP:
                    pt = this.PointToControl(new Point(m.LParam.ToInt32()));
                    if (!this.DesignMode)
                        this.RaiseContextMenu();
                    if (mousePressed)
                    {
                        mousePressed = false;
                        this.OnNonClientClick(EventArgs.Empty);
                    }
                    this.OnNonClientMouseUp(new MouseEventArgs(MouseButtons.Right, 0, pt.X, pt.Y, 0));
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCXBUTTONDOWN:
                    this.mousePressed = true;
                    pt = this.PointToControl(new Point(GlassUtilities.LOWORD(m.LParam.ToInt32())));
                    MouseButtons button;
                    if (GlassUtilities.HIWORD(m.LParam.ToInt32()) == 1)
                        button = MouseButtons.XButton1;
                    else
                        button = MouseButtons.XButton2;
                    this.OnNonClientMouseDown(new MouseEventArgs(button, 0, pt.X, pt.Y, 0));
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_NCXBUTTONUP:
                    if (this.mousePressed)
                    {
                        this.mousePressed = false;
                        this.OnNonClientClick(EventArgs.Empty);
                    }
                    pt = this.PointToControl(new Point(GlassUtilities.LOWORD(m.LParam.ToInt32())));
                    if (GlassUtilities.HIWORD(m.LParam.ToInt32()) == 1)
                        button = MouseButtons.XButton1;
                    else
                        button = MouseButtons.XButton2;
                    this.OnNonClientMouseUp(new MouseEventArgs(button, 0, pt.X, pt.Y, 0));
                    break;

                case (int)NativeMethods.USER32.WindowMessage.WM_WINDOWPOSCHANGING:
                case (int)NativeMethods.USER32.WindowMessage.WM_WINDOWPOSCHANGED:
                    this.InvokeNCPaint();
                    break;

            }
        }

        private IntPtr GetHRegion()
        {
            if (this.Parent == null)
                return IntPtr.Zero;

            //Define a Clip Region to pass back to WM_NCPAINTs wParam.
            //Must be in Screen Coordinates.
            NativeMethods.USER32.WINDOWINFO wi = new NativeMethods.USER32.WINDOWINFO();
            wi.cbSize = Marshal.SizeOf(wi);
            NativeMethods.USER32.GetWindowInfo(this.Handle, ref wi);

            Region Rgn = new Region(wi.rcWindow.ToRectangle());

            IntPtr hRegion;

            using (Graphics g = this.CreateGraphics())
                hRegion = Rgn.GetHrgn(g);

            Rgn.Dispose();

            return hRegion;
        }

        private void NCPaint()
        {
            if (this.Parent == null)
                return;
            if (this.Width <= 0 || this.Height <= 0)
                return;

            IntPtr windowDC = NativeMethods.USER32.GetDCEx(this.Handle, IntPtr.Zero, 
                NativeMethods.USER32.DCXFLAGS.CACHE | NativeMethods.USER32.DCXFLAGS.WINDOW |
                NativeMethods.USER32.DCXFLAGS.CLIPSIBLINGS | NativeMethods.USER32.DCXFLAGS.PARENTCLIP | 
                NativeMethods.USER32.DCXFLAGS.LOCKWINDOWUPDATE);

            if (windowDC.Equals(IntPtr.Zero))
                return;

            this.NCPaint(windowDC);

            if (NativeMethods.USER32.ReleaseDC(this.Handle, windowDC) == 0)
                throw new OperationCanceledException("NCPaint Device Context was not released.");

        }

        [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "GlassUI.NativeMethods+GDI32.SelectClipRgn(System.IntPtr,System.IntPtr)")]
        private void NCPaint(IntPtr hdc)
        {
            using (Graphics g = Graphics.FromHdc(hdc))
            {
                using (BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current)
                {
                    using (BufferedGraphics myBuffer = currentContext.Allocate(g, new Rectangle(Point.Empty, this.Size)))
                    {
                        // Define a Clip Region to exclude the Client Area.
                        Rectangle r = new Rectangle();
                        NativeMethods.USER32.WINDOWINFO wi = new NativeMethods.USER32.WINDOWINFO();
                        wi.cbSize = Marshal.SizeOf(wi);
                        NativeMethods.USER32.GetWindowInfo(this.Handle, ref wi);
                        r.X = wi.rcClient.left - wi.rcWindow.left;
                        r.Y = wi.rcClient.top - wi.rcWindow.top;
                        r.Width = wi.rcClient.right-wi.rcClient.left;
                        r.Height = wi.rcClient.bottom-wi.rcClient.top;

                        Rectangle winRect = wi.rcWindow.ToRectangle();
                        Rectangle clientRect = wi.rcClient.ToRectangle();

                        Region Rgn = new Region(this.RectangleToControl(winRect));

                        Rectangle headerBounds = new Rectangle(winRect.Left, clientRect.Top, winRect.Width, clientRect.Height);
                        Rgn.Exclude(this.RectangleToControl(headerBounds));

                        // Apply the Clip Region to the WindowDC
                        IntPtr hRgn = Rgn.GetHrgn(myBuffer.Graphics);
                        if (!hRgn.Equals(IntPtr.Zero))
                            NativeMethods.GDI32.SelectClipRgn(hdc, hRgn);

                        // Allow Custom Painting of the NonClientArea
                        PaintEventArgs ev = new PaintEventArgs(myBuffer.Graphics, r);
                        this.OnPaintNonClient(ev);

                        // Transfer the buffer image to the nonclient area
                        myBuffer.Render(hdc);

                        // Clean Up
                        NativeMethods.GDI32.SelectClipRgn(hdc, IntPtr.Zero);
                        NativeMethods.GDI32.DeleteObject(hRgn);
                        Rgn.Dispose();

                    }                
                }

            }
        }

        internal void InvokeNCPaint()
        {
            if (this.Created && !this.IsDisposed)
                NativeMethods.USER32.SendMessage(this.Handle, NativeMethods.USER32.WindowMessage.WM_NCPAINT, (IntPtr)1, IntPtr.Zero);
        }

        private void RaiseContextMenu()
        {
            Point point = Control.MousePosition;
            if (this.ContextMenu != null)
            {
                this.ContextMenu.Show(this, this.PointToClient(point));
                return;
            }
            if (this.ContextMenuStrip != null)
            {
                this.ContextMenuStrip.Show(this, this.PointToClient(point));
                return;
            }
            NativeMethods.USER32.SendMessage(this.Parent.Handle, NativeMethods.USER32.WindowMessage.WM_CONTEXTMENU, this.Handle, GlassUtilities.MAKELPARAM(point.X, point.Y));
        }

        internal Point PointToControl(Point point)
        {
            Point pt = this.Parent.PointToScreen(this.Bounds.Location);
            if (this.RightToLeft == RightToLeft.Yes)
                pt.Offset(-this.Bounds.Width, 0);
            point.Offset(-pt.X, -pt.Y);
            return point;
        }

        internal Rectangle RectangleToControl(Rectangle rectangle)
        {
            if (this.Parent == null)
                return Rectangle.Empty;
            Point pt = this.Parent.PointToScreen(this.Bounds.Location);
            if (this.RightToLeft == RightToLeft.Yes)
                pt.Offset(-this.Bounds.Width, 0);
            rectangle.Offset(-pt.X, -pt.Y);
            return rectangle;
        }

        internal Rectangle RectangleToNonClient(Rectangle rectangle)
        {
            Rectangle rc = this.RectangleToControl(this.RectangleToScreen(rectangle));

            bool RTL = this.RightToLeft == RightToLeft.Yes;
            if (RTL)
                rc.Offset(0, 0);
            return rc;
        }

        #region Protected Methods

        [EditorBrowsable(EditorBrowsableState.Advanced)]
        [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")]
        protected virtual void OnNonClientCalcSize(ref Rectangle rc)
        {
            int headerHeight = this.HeaderFont.Height + 12;
            rc.Y += headerHeight;
            rc.Height -= headerHeight;
        }

        protected virtual void OnPaintNonClient(PaintEventArgs pe)
        {
            pe.Graphics.SetClip(this.RectangleToNonClient(this.ClientRectangle), System.Drawing.Drawing2D.CombineMode.Exclude);
            this.DrawParentBackground(pe.Graphics);

            Rectangle rc = new Rectangle(0, 0, this.Width, this.headerFont.Height + 12);
            this.DrawHeader(pe.Graphics, rc);

            if (this.PaintNonClient != null)
                this.PaintNonClient(this, pe);

            pe.Graphics.ResetClip();
        }

        protected virtual void OnNonClientClick(EventArgs e)
        {
            if (this.NonClientClick != null)
                this.NonClientClick(this, e);
        }

        protected virtual void OnNonClientDoubleClick(EventArgs e)
        {
            if (this.NonClientDoubleClick != null)
                this.NonClientDoubleClick(this, e);
        }

        protected virtual void OnNonClientMouseEnter(EventArgs e)
        {
            if (this.NonClientMouseEnter != null)
                this.NonClientMouseEnter(this, e);
            this.InvokeNCPaint();
        }

        protected virtual void OnNonClientMouseHover(EventArgs e)
        {
            if (this.NonClientMouseHover != null)
                this.NonClientMouseHover(this, e);
        }

        protected virtual void OnNonClientMouseLeave(EventArgs e)
        {
            if (this.NonClientMouseLeave != null)
                this.NonClientMouseLeave(this, e);
            this.InvokeNCPaint();
        }

        protected virtual void OnNonClientMouseDown(MouseEventArgs e)
        {
            if (this.NonClientMouseDown != null)
                this.NonClientMouseDown(this, e);
        }

        protected virtual void OnNonClientMouseMove(MouseEventArgs e)
        {
            if (this.NonClientMouseMove != null)
                this.NonClientMouseMove(this, e);
        }

        protected virtual void OnNonClientMouseUp(MouseEventArgs e)
        {
            if (this.NonClientMouseUp != null)
                this.NonClientMouseUp(this, e);
        }

        protected void UpdateNonClient()
        {
            if (this.Created)
            {
                NativeMethods.USER32.SetWindowPos(this.Handle, (IntPtr)NativeMethods.USER32.HWND_NOTOPMOST, 0, 0, 0, 0,
                    NativeMethods.USER32.SETWINDOWPOS.NOACTIVATE
                    | NativeMethods.USER32.SETWINDOWPOS.NOMOVE
                    | NativeMethods.USER32.SETWINDOWPOS.NOSIZE
                    | NativeMethods.USER32.SETWINDOWPOS.NOZORDER
                    | NativeMethods.USER32.SETWINDOWPOS.FRAMECHANGED
                );
            }
        }

        #endregion

        internal void DrawParentBackground(Graphics graphics)
        {
            if (this.Parent == null)
                return;

            //Simulate Transparency
            System.Drawing.Drawing2D.GraphicsContainer g = graphics.BeginContainer();
            Rectangle translateRect = this.Bounds;
            graphics.TranslateTransform(-this.Left, -this.Top);
            PaintEventArgs pe = new PaintEventArgs(graphics, translateRect);
            this.InvokePaintBackground(this.Parent, pe);
            this.InvokePaint(this.Parent, pe);
            graphics.ResetTransform();
            graphics.EndContainer(g);

        }

        internal virtual void DrawHeader(Graphics graphics, Rectangle bounds)
        {
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.CompositingQuality = CompositingQuality.HighQuality;

            GlassForm form = this.FindForm() as GlassForm;

            bool glassify = form == null ? false : form.ControlIsOnGlass(this.Parent);

            Rectangle rc = bounds;
            rc.Width--;
            rc.Height--;

            using (GraphicsPath path = GlassUtilities.RoundedRectangle(bounds, 2))
            {
                graphics.SetClip(path, CombineMode.Replace);
                GlassUtilities.DrawGlowGradient(graphics, bounds, glassify ? Color.FromArgb(128, this.HeaderBackColor) : this.HeaderBackColor, Color.Empty, ControlState.Normal);
                graphics.ResetClip();
                GlassUtilities.DrawRoundedBorder(graphics, bounds, 2, Corners.All, Color.Empty);
            }

            bounds.Inflate(-4, 0);
            bounds.Width -= 4;

            Image img = this.Image;

            if (this.ImageList != null)
            {
                if (this.ImageIndex != -1)
                    if (this.ImageList.Images.Count > this.ImageIndex)
                        img = this.ImageList.Images[this.ImageIndex];
                if (this.ImageKey.Length > 0)
                    img = this.ImageList.Images[ImageKey];
            }

            GlassUtilities.RenderStandardContent(graphics, bounds, this.Text, this.HeaderFont, img, ContentAlignment.MiddleCenter, ContentAlignment.MiddleLeft, TextImageRelation.ImageBeforeText, this.HeaderForeColor, false, 8, this.Enabled, TextFormatFlags.EndEllipsis);

            StackedPanelControl owner = this.Parent as StackedPanelControl;
            if (owner != null)
            {
                rc.Inflate(-1, -1);
                if (owner.Focused && this.ShowFocusCues && owner.TabStop && owner.StackedPanels[owner.SelectedIndex] == this)
                    ControlPaint.DrawFocusRectangle(graphics, rc, this.ForeColor, this.BackColor);
            }

        }

    }

}
